import requests
import json
import time
from typing import Optional, Dict, Any

import os
#音乐平台本地拉取音频资源
class MusicAPI:
    def __init__(self):
        self.base_song_list_url = "https://music.wjhe.top/api/music/kuwo/search"
        self.base_song_detail_url = "https://music.wjhe.top/api/music/kuwo/url"
        self.max_retries = 3;
        self.headers = {
            'Cookie': 'Hm_lvt_5bf7ca0ad4dc414f31a990e7fbff5083=1751717525,1752322450,1752324298,1753280409; HMACCOUNT=64F1E05391FEAB29; Hm_lpvt_5bf7ca0ad4dc414f31a990e7fbff5083=1753280443; access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtYXhUaW1lIjo2MDQ4MDAsImVmZmVjdGl2ZVRpbWUiOjE3NTMyODA0NTAsImlzc3VlVGltZSI6MTc1MzI4MDQ1MCwiRGF0YSI6IntcImlkXCI6NDUsXCJ1c2VySURcIjpcImxpbnV4ZG9cIixcInVzZXJOYW1lXCI6XCJsaW51eGRvXCJ9In0=.b5bd59e1afc80f0323b23528912e03ef8a9e97b56250847a65c5c9b378fc0e7a',
            'User-Agent': 'Mozilla/5.0',
            'Accept': '*/*',
            'Cache-Control': 'no-cache',
            'Host': 'music.wjhe.top',
            'Accept-Encoding': 'gzip, deflate, br',
            'Connection': 'keep-alive',

        }
        self.base_song_download_path = r"C:\workspace\xiaozhi\xiaozhi-esp32-server-1.0\main\xiaozhi-server\music";
        self.session = requests.Session()
        self.session.headers.update(self.headers)

    #歌曲列表
    def get_song_list(self,
                       key: str,
                       page_index: int = 1,
                       page_size: int = 20) -> Optional[Dict[str, Any]]:
        """
        获取音乐列表，支持重试机制

        Args:
            key: 搜索关键词
            page_index: 页码
            page_size: 每页数量
            max_retries: 最大重试次数

        Returns:
            Optional[Dict]: 响应数据或None
        """
        params = {
            'key': key,
            'pageIndex': page_index,
            'pageSize': page_size
        }
        response = self.common_get_request(params, self.base_song_list_url);

        result = response.json()
        # 使用列表保持原始顺序
        music = []
        if result.get("data") and result["data"].get("data"):
            for song in result["data"]["data"]:
                if song.get("ID"):
                    music.append({'song_id':song["ID"],'song_name':song["name"]})

        return music


    #歌曲详情
    def get_song_detail(self, song_id) -> Optional[Dict[str, Any]]:
        """
        获取音乐详情，支持重试机制
        Args:
            song_id: 歌曲id

        Returns:
            Optional[Dict]: 响应数据或None
        """
        params = {
            'ID': song_id,
            'quality': '320',
            'format': 'mp3'
        }

        response = self.common_get_request(params, self.base_song_detail_url);


        return response.url

    #公共请求方法直接返回指定的json数据
    def common_get_request(self, params, url) -> Optional[Dict[str, Any]]:
        for retry in range(self.max_retries):
            try:
                response = self.session.get(
                    url=url,
                    params=params,
                    timeout=10
                )

                return response

            except requests.exceptions.RequestException as e:
                print(f"请求出错 (重试 {retry + 1}/{self.max_retries}): {str(e)}")
                if retry < self.max_retries - 1:
                    time.sleep(2 ** retry)  # 指数退避
                continue

            except json.JSONDecodeError as e:
                print(f"解析响应数据出错: {str(e)}")
                return None

            except Exception as e:
                print(f"发生未知错误: {str(e)}")
                return None

    #下载歌曲到本地
    def download_song(self,song_url,song_name):
        #只能用这个 使用公共的就会下载0k
        response = requests.get(song_url, headers={'User-Agent': 'Mozilla/5.0',}, stream=True, timeout=20)
        # 检查响应状态码
        if response.status_code == 200:
            # 创建目标文件夹（如果不存在的话）
            # os.makedirs(save_path, exist_ok=True)
            # 写入文件
            with open(self.base_song_download_path+"\\"+song_name+".mp3", 'wb') as f:
                for chunk in response.iter_content(chunk_size=8192):
                    f.write(chunk)

            print(f"✅ 歌曲下载成功：{song_name}")
        else:
            print(f"❌ 下载失败，状态码：{response.status_code}")

    def main(song_input_name):
        # 创建API实例
        api = MusicAPI()

        # 搜索音乐
        song_list = api.get_song_list(
            key=str(song_input_name),
            page_index=1,
            page_size=20
        )

        if song_list:
            # 打印结果
            #暂时先取第一个 因为这是最契合的筛选结果
            best_match_song = song_list[0]
            #拿到歌曲下载路径
            song_download_url = api.get_song_detail(best_match_song.get("song_id"))
            #下载到本地
            api.download_song(song_download_url,best_match_song.get("song_name"))
            return best_match_song.get("song_name")
        else:
            return None


if __name__ == "__main__":
    api = MusicAPI()
    api.main('qq爱')




